package model

import (
	"strings"
	"os"
	"io/ioutil"
	"fmt"
	"bytes"
	"global/libs/structs"
	"strconv"
)

type Kline struct {
	Id        int    `json:"id" xorm:"not null pk autoincr INT(11)"`
	Exchange  string `json:"exchange" xorm:"not null default '' unique(Index_e_s_t) VARCHAR(16)"`
	Symbol    string `json:"symbol" xorm:"not null default '' unique(Index_e_s_t) VARCHAR(32)"`
	CoinBase  string `json:"coin_base" xorm:"not null default '' VARCHAR(16)"`
	CoinQuote string `json:"coin_quote" xorm:"not null default '' VARCHAR(16)"`
	Time      string `json:"time" xorm:"not null default '' unique(Index_e_s_t) index CHAR(13)"`
	Open      string `json:"open" xorm:"not null default 0.0000000000 DECIMAL(40,10)"`
	High      string `json:"high" xorm:"not null default 0.0000000000 DECIMAL(40,10)"`
	Low       string `json:"low" xorm:"not null default 0.0000000000 DECIMAL(40,10)"`
	Close     string `json:"close" xorm:"not null default 0.0000000000 DECIMAL(40,10)"`
	Volume    string `json:"volume" xorm:"not null default 0.0000000000 DECIMAL(40,10)"`
	Datetime  string `json:"datetime" xorm:"not null default '' VARCHAR(32)"`
}

type klineModel struct {}

var KlineModel = new(klineModel)

// 检查表是否存在
func (m *klineModel) IsTableExists(tableName string) (bool, error) {
	return MainDB.IsTableExist(tableName)
}

// 获取最大值
func (m *klineModel) GetMax(tableName string, exchange string,
	symbol *structs.Symbol) (int, error) {

		sql := fmt.Sprintf("SELECT max(time) as m FROM `%s` WHERE exchange='%s' AND symbol='%s_%s'",
			tableName, exchange, symbol.From, symbol.To)
		res, err := MainDB.Query(sql)
		if err != nil {
			return 0, err
		}

		if len(res[0]) > 0 {
			max, err := strconv.Atoi(string(res[0]["m"]))
			if err != nil {
				return 0, err
			}
			return max, nil
		}
		return 0, nil
}

func (m *klineModel) InsertMulti(table string, datas []*Kline) (bool, error) {
	items, err := MainDB.Table(table).Insert(datas)
	if err != nil {
		return false, err
	}
	return items > 0, nil
}

// 插入一条
func (*klineModel) Insert(table string, data *Kline) (bool, error) {
	rows, err := MainDB.Table(table).InsertOne(data)
	if err != nil {
		return false, err
	}
	return rows > 0, err
}

func (*klineModel) Update(table string, tmp *Kline) (bool, error) {
	row, err := MainDB.Where("time=? AND exchange=? AND symbol=?",
		tmp.Time, tmp.Exchange, tmp.Symbol).Update(tmp)
	if err != nil {
		return false, err
	}
	return row > 0, nil
}

// 表中是否有记录
func (m *klineModel) HasItem(tableName string, exchange string,
	symbol *structs.Symbol) (bool, error) {
	kline := new(Kline)
	total, err := MainDB.
		Table(tableName).
		Where("exchange=?", exchange).
		Where("symbol=?", symbol.From + "_" + symbol.To).
		Count(kline)
	return total > 0, err
}

// 创建一个表
func (m *klineModel) CreateTable(tableName string) (bool, error) {
	sql, err := m.getSqlFile()
	if err != nil {
		return false, err
	}
	sql = fmt.Sprintf(sql, tableName)

	buf := new(bytes.Buffer)
	buf.ReadFrom(strings.NewReader(sql))

	res, err := MainDB.Import(buf)
	if err != nil {
		return false, err
	}

	return len(res) > 0, nil
}

func (m *klineModel) getSqlFile() (string, error) {
	file, err := os.Open("./kline.sql")
	if err != nil {
		return "", err
	}
	data, err := ioutil.ReadAll(file)
	if err != nil {
		return "", err
	}
	return string(data), nil
}